/**
 * Created by xinxinran on 15/11/27.
 */
'use strict';
define(['frame/XFrame_Graph', 'frame/BaseShape', 'frame/CommonShape'], function(XFrame_Graph, BaseShape, CommonShape){

    var Gomoku = {}, GomokuShape = {}, ChessPlaceEvents = {}, GomokuStatus = {
        gameStarted : false,
        gamersReady : 0,
        usedPlaces : [],
        mode : 0,
        nowColor : 0,
        gamerInfo : null,
        putToken : null
    },  ChessPlaces = {}, lastChess = null, changeChessUser, baseSize, canvasContainer, firstInit = true;

    changeChessUser = function(){
        if(!GomokuStatus.mode){
            return;
        }

        GomokuStatus.nowColor = GomokuStatus.nowColor ^ 3;
    };

    GomokuShape.CheckerBoard = BaseShape.extend({
        init : function(conf){
            var i, crossPoints = [];
            conf = conf || {};
            this.width = this.height = conf.baseSize;
            this.dragable = false;
            this.borderColor = '#666';

            this.innerDis = ((conf.baseSize - 20) / 15) | 0;
            this.outerDis = this.innerDis - 8;

            this.minEdge = this.innerDis;
            this.maxEdge = conf.baseSize - this.innerDis;
            this.gridDis = (this.maxEdge - this.minEdge) / 14;
            for(i = 0; i < 15; i++){
                crossPoints.push(this.minEdge + this.gridDis * i);
            }

            this.crossPoints = crossPoints;
            this.smartPointRadius = 3;
        },

        drawDefine : function(){
            var dd = new XFrame_Graph.drawDefiner(), i;
            dd.style('Stroke', this.borderColor);
            dd.style('LineWidth', 1);
            dd.draw('Rect', this.posX + this.outerDis, this.posY + this.outerDis,
                this.width - (this.outerDis * 2), this.height - (this.outerDis * 2));

            dd.style('LineWidth', 4);
            dd.draw('Rect', this.posX + this.innerDis, this.posY + this.innerDis,
                this.width - (this.innerDis * 2), this.height - (this.innerDis * 2));

            dd.style('LineWidth', 1);

            for(i = 1; i < 15; i++){
                dd.draw('Line', this.minEdge, this.crossPoints[i], this.maxEdge, this.crossPoints[i]);
                dd.draw('Line', this.crossPoints[i], this.minEdge, this.crossPoints[i], this.maxEdge);
            }

            dd.style('Fill', this.borderColor);
            dd.draw('FilletRect', this.crossPoints[7] - this.smartPointRadius, this.crossPoints[7] - this.smartPointRadius
                , this.smartPointRadius * 2, this.smartPointRadius * 2, this.smartPointRadius);

            dd.draw('FilletRect', this.crossPoints[3] - this.smartPointRadius, this.crossPoints[3] - this.smartPointRadius
                , this.smartPointRadius * 2, this.smartPointRadius * 2, this.smartPointRadius);

            dd.draw('FilletRect', this.crossPoints[3] - this.smartPointRadius, this.crossPoints[11] - this.smartPointRadius
                , this.smartPointRadius * 2, this.smartPointRadius * 2, this.smartPointRadius);

            dd.draw('FilletRect', this.crossPoints[11] - this.smartPointRadius, this.crossPoints[3] - this.smartPointRadius
                , this.smartPointRadius * 2, this.smartPointRadius * 2, this.smartPointRadius);

            dd.draw('FilletRect', this.crossPoints[11] - this.smartPointRadius, this.crossPoints[11] - this.smartPointRadius
                , this.smartPointRadius * 2, this.smartPointRadius * 2, this.smartPointRadius);

            return dd.getCommands();
        }
    });

    GomokuShape.ChessPlace = BaseShape.extend({
        init : function(conf) {
            conf = conf || {};
            this.centerX = conf.centerX;
            this.centerY = conf.centerY;

            this.posX = conf.centerX - (conf.gridDis / 2);
            this.posY = conf.centerY - (conf.gridDis / 2);

            this.width = this.height = conf.gridDis;
            this.borderColor = '#FF7164';
            this.newBorderColor = '#FF4738';

            this.posTag = conf.posTag;
            this.chessRadius = (conf.gridDis - 8) / 2;

            this.used = false;

            this.canActive = false;
            this.canInActive = false;
            this.canProcessRootEvent = true;
        },

        drawDefine : function(){
            var dd = new XFrame_Graph.drawDefiner(), focusLineSize = this.width / 3, passLineSize = this.width / 4;

            //dd.style('Stroke', '#eeeeee');
            //dd.draw('Rect', this.posX, this.posY, this.width, this.height);

            dd.changeEditType('hoverEnable');
            dd.style('Stroke', this.borderColor);
            dd.style('LineWidth', 2);

            dd.draw('Line', this.posX , this.posY, this.posX + focusLineSize, this.posY);
            dd.draw('Line', this.posX , this.posY, this.posX, this.posY + focusLineSize);

            dd.draw('Line', this.posX + this.width - focusLineSize , this.posY, this.posX + this.width, this.posY);
            dd.draw('Line', this.posX + this.width , this.posY, this.posX + this.width, this.posY + focusLineSize);

            dd.draw('Line', this.posX, this.posY + this.height - focusLineSize, this.posX, this.posY + this.height);
            dd.draw('Line', this.posX, this.posY + this.height, this.posX + focusLineSize, this.posY + this.height);

            dd.draw('Line', this.posX + this.width - focusLineSize, this.posY + this.height, this.posX + this.width, this.posY + this.height);
            dd.draw('Line', this.posX + this.width, this.posY + this.height, this.posX + this.width, this.posY + this.height - focusLineSize);


            dd.changeEditType('hoverDisable');
            dd.style('Stroke', this.borderColor);
            dd.style('LineWidth', 2);
            dd.draw('Line', this.centerX - passLineSize, this.centerY - passLineSize, this.centerX + passLineSize, this.centerY + passLineSize);
            dd.draw('Line', this.centerX + passLineSize, this.centerY - passLineSize, this.centerX - passLineSize, this.centerY + passLineSize);

            dd.changeEditType('blackUsed');
            dd.style('Fill', {
                creator : [this.posX + this.width * 2, this.posY + this.height * 2 , this.posX, this.posY],
                stops : [[0, '#eee'], [0.89, '#151515'], [0.89, '#151515'], [1, '#151515']]
            });

            dd.draw('FilletRect', this.posX + 2, this.posY + 2
                , this.chessRadius * 2, this.chessRadius * 2, this.chessRadius);

            dd.changeEditType('whiteUsed');
            dd.style('Fill', {
                creator : [this.posX + this.width * 2, this.posY + this.height * 2 , this.posX, this.posY],
                stops : [[0, '#fff'], [0.89, '#dedede'], [0.89, '#dedede'], [1, '#dedede']]
            });

            dd.draw('FilletRect', this.posX + 2, this.posY + 2
                , this.chessRadius * 2, this.chessRadius * 2, this.chessRadius);

            dd.changeEditType('blackUsedNew');
            dd.style('Shadow', this.newBorderColor, 10);
            //
            //dd.draw('Line', this.posX , this.posY, this.posX + focusLineSize, this.posY);
            //dd.draw('Line', this.posX , this.posY, this.posX, this.posY + focusLineSize);
            //
            //dd.draw('Line', this.posX + this.width - focusLineSize , this.posY, this.posX + this.width, this.posY);
            //dd.draw('Line', this.posX + this.width , this.posY, this.posX + this.width, this.posY + focusLineSize);
            //
            //dd.draw('Line', this.posX, this.posY + this.height - focusLineSize, this.posX, this.posY + this.height);
            //dd.draw('Line', this.posX, this.posY + this.height, this.posX + focusLineSize, this.posY + this.height);
            //
            //dd.draw('Line', this.posX + this.width - focusLineSize, this.posY + this.height, this.posX + this.width, this.posY + this.height);
            //dd.draw('Line', this.posX + this.width, this.posY + this.height, this.posX + this.width, this.posY + this.height - focusLineSize);

            dd.style('Fill', {
                creator : [this.posX + this.width * 2, this.posY + this.height * 2 , this.posX, this.posY],
                stops : [[0, '#eee'], [0.89, '#151515'], [0.89, '#151515'], [1, '#151515']]
            });

            dd.draw('FilletRect', this.posX + 2, this.posY + 2
                , this.chessRadius * 2, this.chessRadius * 2, this.chessRadius);

            dd.changeEditType('whiteUsedNew');
            dd.style('Shadow', this.newBorderColor, 10);
            //
            //dd.draw('Line', this.posX , this.posY, this.posX + focusLineSize, this.posY);
            //dd.draw('Line', this.posX , this.posY, this.posX, this.posY + focusLineSize);
            //
            //dd.draw('Line', this.posX + this.width - focusLineSize , this.posY, this.posX + this.width, this.posY);
            //dd.draw('Line', this.posX + this.width , this.posY, this.posX + this.width, this.posY + focusLineSize);
            //
            //dd.draw('Line', this.posX, this.posY + this.height - focusLineSize, this.posX, this.posY + this.height);
            //dd.draw('Line', this.posX, this.posY + this.height, this.posX + focusLineSize, this.posY + this.height);
            //
            //dd.draw('Line', this.posX + this.width - focusLineSize, this.posY + this.height, this.posX + this.width, this.posY + this.height);
            //dd.draw('Line', this.posX + this.width, this.posY + this.height, this.posX + this.width, this.posY + this.height - focusLineSize);

            dd.style('Fill', {
                creator : [this.posX + this.width * 2, this.posY + this.height * 2 , this.posX, this.posY],
                stops : [[0, '#fff'], [0.89, '#dedede'], [0.89, '#dedede'], [1, '#dedede']]
            });

            dd.draw('FilletRect', this.posX + 2, this.posY + 2
                , this.chessRadius * 2, this.chessRadius * 2, this.chessRadius);

            return dd.getCommands();
        }
    });

    ChessPlaceEvents.mouseenter = function(){
        if(!GomokuStatus.gameStarted || this.used){
            return;
        }

        this.status = (GomokuStatus.nowColor & GomokuStatus.mode) ? 'hoverEnable' : 'hoverDisable';
        this.refresh();
    };

    ChessPlaceEvents.mouseleave = function(){
        if(!GomokuStatus.gameStarted || this.used){
            return;
        }

        this.status = 'default';
        this.refresh();
    };

    ChessPlaceEvents.click = function(){
        if(!GomokuStatus.gameStarted || this.used){
            return;
        }

        if(!(GomokuStatus.nowColor & GomokuStatus.mode)){
            return ;
        }

        Gomoku.notifyChess(this.posTag, GomokuStatus.putToken);
    };

    Gomoku.initGomoku = function($canvas, socketIO){
        if(!$canvas || !$canvas.jquery){
            throw '[init gomoku]Bad parameter..$canvas';
        }

        baseSize = Math.min($canvas.width(), $canvas.height());

        if(baseSize < 800){
            throw '[init gomoku] canvas size is too small';
        }

        canvasContainer = $canvas;

        socketIO && registerSocketIo(socketIO);
    };

    function registerSocketIo(socketIO){
        Gomoku.socket = socketIO;

        socketIO.on('gameStart', function(gameInfo){
            GomokuStatus.gameStarted = true;
            GomokuStatus.mode = gameInfo.mode;
            GomokuStatus.nowColor = gameInfo.nowColor;
        });

        socketIO.on('putToken', function(token){
            console.log('my token is : ' + token);
            GomokuStatus.putToken = token;
        });

        socketIO.on('putChess', function(data){
            Gomoku.putChess(data.x + '|' + data.y, data.nowColor);
        });

        socketIO.on('delChess', function(data){
            var posTag = data.x + '|' + data.y, targetChess = ChessPlaces[posTag], lastInfo = data.last;

            if(targetChess){

                targetChess.status = 'default';
                targetChess.oriStatus = 'default';
                targetChess.used = false;

                if(lastInfo){
                    posTag = lastInfo[0] + '|' + lastInfo[1];
                    targetChess = ChessPlaces[posTag];
                    targetChess && (targetChess.status = targetChess.status + 'New');
                    lastChess = targetChess;
                }else{
                    lastChess = null;
                }

                XFrame_Graph.refresh();
                changeChessUser();
            }
        });

        socketIO.on('clean', function(){
            for(var tag in ChessPlaces){
                if(ChessPlaces.hasOwnProperty(tag)){
                    ChessPlaces[tag].status = 'default';
                    ChessPlaces[tag].oriStatus = 'default';
                    ChessPlaces[tag].used = false;
                }
            }

            lastChess = null;

            XFrame_Graph.refresh();
        });

        socketIO.on('resetChess', function(chessObj){
            var targetChess, posTag, chessMap = chessObj.map, lastChessObj = chessObj.last;
            for(posTag in chessMap){
                if(chessMap.hasOwnProperty(posTag)){
                    targetChess = ChessPlaces[posTag];
                    if(targetChess){
                        targetChess.used = true;
                        targetChess.status = (chessMap[posTag] & 1) ? 'blackUsed' : 'whiteUsed';
                    }
                }
            }

            if(lastChessObj){
                targetChess = ChessPlaces[lastChessObj[0] + '|' + lastChessObj[1]];
                if(targetChess){
                    targetChess.oriStatus = targetChess.status;
                    targetChess.status = targetChess.oriStatus + 'New';
                }

                lastChess = targetChess;
            }else{
                lastChess = null;
            }

            XFrame_Graph.refresh();
        });
    }

    function newGomoku(){

        var checkerboard, i, j, cp, crosses, gridDis;

        XFrame_Graph.initCanvas(canvasContainer);

        checkerboard = new GomokuShape.CheckerBoard({
            posX : 0,
            poxY : 0,
            baseSize : baseSize
        });

        checkerboard.regist();

        crosses = checkerboard.crossPoints;
        gridDis = checkerboard.gridDis;
        for(i = 0; i < 15; i++){
            for(j = 0; j < 15; j++){
                cp = new GomokuShape.ChessPlace({
                    centerX : crosses[i],
                    centerY : crosses[j],
                    posTag : i + '|' + j,
                    gridDis : gridDis,
                    parentShape : checkerboard
                });

                cp.regist();

                cp.onEvent('mousein', ChessPlaceEvents.mouseenter);
                cp.onEvent('mouseout', ChessPlaceEvents.mouseleave);
                cp.onEvent('click', ChessPlaceEvents.click);

                ChessPlaces[cp.posTag] = cp;

            }
        }

        XFrame_Graph.show();
    }

    function clearGomoku(){
        for(var tag in ChessPlaces){
            if(ChessPlaces.hasOwnProperty(tag)){
                ChessPlaces[tag].status = 'default';
            }
        }
        GomokuStatus.gamersReady = 0;
        GomokuStatus.gameStarted = false;
        GomokuStatus.usedPlaces = [];

        XFrame_Graph.refresh();
    }

    Gomoku.notifyChess = function(posTag, token){
        var p = posTag.split('|');
        Gomoku.socket.emit('putChess', {x : +p[0], y : +p[1], t : token});
    };

    Gomoku.putChess = function(posTag, mode){
        var targetChess = ChessPlaces[posTag];
        if(!targetChess || targetChess.used){
            throw '[gomoku put chess] invalid status or position';
        }

        mode = mode & 3;
        if(!mode){
            throw '';
        }

        if(lastChess){
            lastChess.status = lastChess.oriStatus;
        }

        targetChess.used = true;
        targetChess.oriStatus = (mode & 1) ? 'blackUsed' : 'whiteUsed';
        targetChess.status = targetChess.oriStatus + 'New';
        targetChess.refresh();

        lastChess = targetChess;

        changeChessUser();
    };

    Gomoku.putUser = function(userInfo){
        GomokuStatus.gamerInfo = userInfo;
    };

    Gomoku.startGame = function(){
        if(firstInit){
            firstInit = false;
            newGomoku();
        }else{
            clearGomoku();
        }
        Gomoku.socket.emit('resetChess');
    };

    Gomoku.changeState = function(){

    };

    Gomoku.getState = function(){
        return GomokuStatus
    };

    window.testGomoku = Gomoku;
    return Gomoku;
});